﻿<rules>
  <rule id="Metadata.Core.1002" category="core" target="metadata" specificationsection ="2.2.3.7.2" requirementlevel="must" format="xml" metadata="true">
    <description>The MimeType attribute MUST be used on a &lt;Property&gt; element [MC-CSDL] to indicate the media type of the content to be stored in the property being defined by the XML element.</description>
    <action processor="xslt+rng">
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
        <xsl:template match="/">
          <grammar xmlns="http://relaxng.org/ns/structure/1.0">
            <!-- Apply XSLT to get the edmx, edm, and m namespace from metadata document. -->
            <xsl:apply-templates select="*[local-name()='Edmx']/*[local-name()='DataServices']"/>
            <start>
              <element>
                <!-- Ignore the Edmx element. -->
                <anyName />
                <ref name="anyAttributes" />
                <element>
                  <!-- Ignore the DataServices element. -->
                  <anyName />
                  <ref name="anyAttributes" />
                  <zeroOrMore>
                    <element>
                      <!-- Ignore the Schema element. -->
                      <anyName />
                      <ref name="anyAttributes" />
                      <interleave>
                        <zeroOrMore>
                          <element name="edm:EntityType">
                            <ref name="anyAttributes" />
                            <interleave>
                              <zeroOrMore>
                                <element name="edm:Property">
                                  <attribute name="Type">
                                    <text />
                                  </attribute>
                                  <ref name="anyAttributes_other_than_edm_Type" />
                                </element>
                              </zeroOrMore>
                              <zeroOrMore>
                                <!-- Elements here must not be Property. -->
                                <ref name="anyElement_other_than_edm_Property_without_edm_Type" />
                              </zeroOrMore>
                            </interleave>
                          </element>
                        </zeroOrMore>
                        <zeroOrMore>
                          <!-- Elements here must not be EntityType. -->
                          <ref name="anyElement_other_than_edm_EntityType" />
                        </zeroOrMore>
                      </interleave>
                    </element>
                  </zeroOrMore>
                </element>
              </element>
            </start>
            <define name="anyContent">
              <zeroOrMore>
                <choice>
                  <attribute>
                    <anyName />
                  </attribute>
                  <text />
                  <ref name="anyElement" />
                </choice>
              </zeroOrMore>
            </define>
            <define name="anyAttributes">
              <zeroOrMore>
                <choice>
                  <attribute>
                    <anyName />
                  </attribute>
                </choice>
              </zeroOrMore>
            </define>
            <define name="anyAttributes_other_than_edm_Type">
              <zeroOrMore>
                <choice>
                  <attribute>
                    <anyName>
                      <except>
                        <name>Type</name>
                      </except>
                    </anyName>
                  </attribute>
                </choice>
              </zeroOrMore>
            </define>
            <define name="anyElement">
              <element>
                <anyName />
                <zeroOrMore>
                  <choice>
                    <attribute>
                      <anyName />
                    </attribute>
                    <text />
                    <ref name="anyElement" />
                  </choice>
                </zeroOrMore>
              </element>
            </define>
            <define name="anyElement_other_than_edm_EntityType">
              <element>
                <choice>
                  <anyName>
                    <except>
                      <nsName>
                        <!-- Apply XSLT to get the edm namespace from metadata document. -->
                        <xsl:apply-templates select="*[local-name()='Edmx']"/>
                      </nsName>
                    </except>
                  </anyName>
                  <nsName>
                    <!-- Apply XSLT to get the edm namespace from metadata document. -->
                    <xsl:apply-templates select="*[local-name()='Edmx']"/>
                    <except>
                      <name>edm:EntityType</name>
                    </except>
                  </nsName>
                </choice>
                <ref name="anyContent" />
              </element>
            </define>
            <define name="anyElement_other_than_edm_Property_without_edm_Type">
              <element>
                <choice>
                  <anyName>
                    <except>
                      <nsName>
                        <!-- Apply XSLT to get the edm namespace from metadata document. -->
                        <xsl:apply-templates select="*[local-name()='Edmx']"/>
                      </nsName>
                    </except>
                  </anyName>
                  <nsName>
                    <!-- Apply XSLT to get the edm namespace from metadata document. -->
                    <xsl:apply-templates select="*[local-name()='Edmx']"/>
                    <except>
                      <name>edm:Property</name>
                    </except>
                  </nsName>
                </choice>
                <ref name="anyAttributes_other_than_edm_Type"/>
                <text/>
                <zeroOrMore>
                  <ref name="anyElement" />
                </zeroOrMore>
              </element>
            </define>
          </grammar>
        </xsl:template>
        <xsl:template name="make-namespace-node">
          <xsl:param name="prefix"/>
          <xsl:param name="uri"/>
          <xsl:attribute name="{ concat($prefix, ':dummy-for-xmlns') }" namespace="{ $uri }"/>
        </xsl:template>
        <xsl:template match="*[local-name()='Edmx']/*[local-name()='DataServices']" xmlns="http://relaxng.org/ns/structure/1.0">
          <xsl:call-template name="make-namespace-node">
            <xsl:with-param name="prefix" select="'edmx'" />
            <xsl:with-param name="uri" select="namespace-uri(/*[local-name()='Edmx'])" />
          </xsl:call-template>
          <xsl:call-template name="make-namespace-node">
            <xsl:with-param name="prefix" select="'edm'" />
            <xsl:with-param name="uri" select="namespace-uri(/*[local-name()='Edmx']/*[local-name()='DataServices']/*[local-name()='Schema'])" />
          </xsl:call-template>
          <xsl:call-template name="make-namespace-node">
            <xsl:with-param name="prefix" select="'m'" />
            <!-- Get m namespace using namespace axis rather than using the query. This is because in some instances m namespace is not on edmx element. -->
            <xsl:with-param name="uri" select="string(//*/namespace::m)" />
          </xsl:call-template>
        </xsl:template>
        <xsl:template name="make-namespace-node-other-than">
          <xsl:param name="prefix"/>
          <xsl:param name="uri"/>
          <xsl:attribute name="{ $prefix }">
            <xsl:value-of select="$uri"/>
          </xsl:attribute>
        </xsl:template>
        <!-- Call make-namespace-node-other-than to make an anonymous namespace. -->
        <xsl:template match="*[local-name()='Edmx']" xmlns="http://relaxng.org/ns/structure/1.0">
          <xsl:call-template name="make-namespace-node-other-than">
            <xsl:with-param name="prefix" select="'ns'" />
            <xsl:with-param name="uri" select="namespace-uri(/*[local-name()='Edmx']/*[local-name()='DataServices']/*[local-name()='Schema'])" />
          </xsl:call-template>
        </xsl:template>
      </xsl:stylesheet>
    </action>
    <errormessage>The MimeType attribute MUST be used on a &lt;Property&gt; element [MC-CSDL] to indicate the media type of the content to be stored in the property being defined by the XML element.</errormessage>
  </rule>
</rules>